#pragma once

#include "RHIBuffer.h"

class BufferView : public RHIBuffer
{
	struct BuilderDetails {

		bool isMultiple;


		VkDeviceSize size;
		VkBufferUsageFlags usage;
		VkSharingMode sharingMode;
		std::vector<VkQueueFlagBits> queueFamilys;

		VkMemoryPropertyFlags memoryProperty;

		VkFormat format;
		VkDeviceSize offset;
		VkDeviceSize range;

		void* data;

		BuilderDetails()
		{
			isMultiple = false;

			size = 0;
			// Have to contain VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT or VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT
			usage = VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
			sharingMode = VK_SHARING_MODE_EXCLUSIVE;
			// VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
			memoryProperty = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;

			format = VK_FORMAT_R8G8B8A8_UNORM;
			offset = 0;
			range = VK_WHOLE_SIZE;

			data = nullptr;
		}
	};

public:

	class Builder : public BuilderBase<BuilderDetails> {
		friend struct BuilderDetails;
	public:
		Builder() noexcept;
		Builder(Builder const& rhs) noexcept;
		Builder(Builder&& rhs) noexcept;
		~Builder() noexcept;
		Builder& operator=(Builder const& rhs) noexcept;
		Builder& operator=(Builder&& rhs) noexcept;

		Builder& SetMultiple(bool isMultiple) noexcept;

		Builder& SetSize(VkDeviceSize size) noexcept;
		Builder& SetUsage(VkBufferUsageFlags usage) noexcept;
		Builder& SetSharingMode(VkSharingMode sharingMode) noexcept;
		Builder& AddQueueFamily(VkQueueFlagBits queueFlag) noexcept;
		Builder& SetMemoryProperty(VkMemoryPropertyFlags memoryProperty) noexcept;

		Builder& SetFormat(VkFormat format) noexcept;
		Builder& SetOffset(VkDeviceSize offset) noexcept;
		Builder& SetRange(VkDeviceSize range) noexcept;

		Builder& SetData(void* data) noexcept;

		RefCountPtr<BufferView> Build();
		RefCountPtr<BufferView> Build(RenderProcess* process, const std::string& name);

	private:
		friend class DescriptorSet;
	};

	BufferView(BuilderDetails& builderDetails);

	virtual void ReleaseResource() override;

	virtual ~BufferView();

	VkBufferView GetBufferView(uint32 index = UINT32_MAX) const;

protected:


	VkFormat mFormat;
	VkDeviceSize mOffset;
	VkDeviceSize mRange;

	std::vector<VkBufferView> mBufferViews;
};